home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 6
/
FM Towns Free Software Collection 6.iso
/
t_os
/
book
/
src
/
file.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-08
|
9KB
|
338 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <ctype.h>
#include <egb.h>
#include <mos.h>
#include "oaklib.h"
#include "file.h"
#include "menu_evt.h"
#include "init.h"
#include "book.h"
#include "lib.h"
#include "menu.h"
LBLOCK *base[LINEBLOCKs] ; /* 行ブロックを指すポインタの配列 */
#if 0
static char *filebuf = NULL ; /* 生のファイルデータ */
static char *ptr = NULL ; /* データ処理用のワーク */
static int readpos = 0L ; /* データ処理用のワーク */
static int fsize = 0L ; /* 現在ファイルの大きさ */
static HEADER filehead = {NULL} ; /* ファイルヘッダ */
static int now_block = -1 ; /* base[]をどこまで使っているか */
static int now_line = 0 ; /* 現在ファイルの行数 */
static int now_linelow = 0 ; /* 現在ファイルの行数 % LINEPTRs */
#endif
static FILE *file_ptr = NULL ;
typedef struct {
char *filebuf ; /* 生のファイルデータ */
char *ptr ; /* データ処理用のワーク */
int readpos ; /* データ処理用のワーク */
int fsize ; /* ファイルの大きさ */
int readsize ; /* ファイルを読み込んだ量 */
int readstep ; /* 分割読み込みする量 */
HEADER filehead ; /* ファイルヘッダ */
int now_block ; /* base[]をどこまで使っているか */
int now_line ; /* 現在ファイルの行数 */
int now_linelow ; /* 現在ファイルの行数 % LINEPTRs */
} HEAD ;
static HEAD head = { NULL, NULL, 0L,0L,0L,0L, {NULL}, -1, 0, 0 } ;
/*
* 渡されたパラメータを行管理テーブルにセットする
*/
static int set_linedata( char *str, int bytes )
{
static LBLOCK *bp = NULL ;
if( ++head.now_linelow >= LINEPTRs )
{
if( ( bp = malloc( sizeof( LBLOCK ) ) ) == NULL )
return ERROR ;
if( ++head.now_block >= LINEBLOCKs )
return ERROR ;
base[head.now_block] = bp ;
head.now_linelow = 0 ;
}
bp->ptr[head.now_linelow].buf = str ;
bp->ptr[head.now_linelow].bytes = bytes ;
head.now_line++ ;
return ERROR+1 ;
}
void backup_file( back_t flag )
{
static back_t status = RESTORE ;
static HEAD tmp_head ;
static LBLOCK *tmp_base[LINEBLOCKs] ;
int i ;
switch( flag )
{
case BACKUP: /* バックアップして、表向きは初期化 */
status = BACKUP ;
tmp_head = head ;
for( i = 0 ; i < LINEBLOCKs ; i++ )
tmp_base[i] = base[i] ;
head.now_block = -1 ;
head.filehead.file = NULL ;
head.filebuf = NULL ;
break ;
case RESTORE: /* backupしてある時だけ */
if( status == BACKUP ) /* backupしてある時だけ */
{
status = RESTORE ;
head = tmp_head ;
*base = *tmp_base ;
}
break ;
case INIT: /* 初期化してしまう */
status = RESTORE ;
break ;
}
}
void free_head( void )
{
int i ;
/* 行管理ブロックを開放 */
for( i = 0 ; i <= head.now_block ; i++ )
free( base[i] ) ;
head.now_block = -1 ;
/* ファイルヘッダのファイル名バッファを開放 */
if( head.filehead.file != NULL )
free( head.filehead.file ), head.filehead.file = NULL ;
}
/* #define beof() (head.readpos > head.fsize) *//* eof? */
static int read_file( void )
{
const readstep = 62 * 1024 ; /* 62KB ずつ読む */
int size, status = 0 ;
if( ( size = head.fsize - head.readsize ) > 0 && file_ptr != NULL )
{
if( size > readstep )
size = readstep ;
status = fread( &head.filebuf[head.readsize], 1,size, file_ptr ) ;
head.readsize += status ;
head.filebuf[head.readsize] = '\0' ; /* ファイル末尾に \0 を追加 */
}
return status ;
}
static int beof( void )
{
if( head.readpos > head.readsize ) /* eof? */
{
if( head.fsize > head.readsize )
{
read_file() ;
return FALSE ;
}
return TRUE ;
}
return FALSE ;
}
static int read_line( void )
{
int i, j, bytes ;
char *p ;
bytes = head.readpos ;
for( p=head.ptr, i=0 ; i < LINEMAX ; p++, i++ )
{
head.readpos++ ;
if( beof() ) /* eof? */
break ;
if( israw( *p ) ) /* そのまま */
;
else if( iskanji( *p ) ) /* 全角文字 */
{
if( i == ( LINEMAX - 1 ) )
{
head.readpos-- ;
break ;
}
/* 全角文字の2バイト目を獲得 */
if( beof() )
break ;
if( iskanji2( *(p+1) ) )
{
p++, head.readpos++, i++ ;
}
}
else if( isctrl( *p ) ) /* 制御コード */
{
if( *p == '\x0D' ) /* リターンコード */
{
head.readpos++, p+=2 ;
if( !beof() && *(p-1) == '\x0A' )
break ;
head.readpos--, p-=2 ;
}
if( *p == '\t' && setup.tabsiz > 0 ) /* タブ */
{
j = setup.tabsiz - ( i % setup.tabsiz ) ;
while( i < LINEMAX && j-- > 0 )
i++ ;
i-- ;
}
else if( setup.disp_ctrl ) /* 一般制御コード */
{
if( i == ( LINEMAX - 1 ) )
{
head.readpos-- ;
break ;
}
else
i++ ;
}
}
}
bytes = head.readpos - bytes ;
if( beof() ) /* eof? */
bytes-- ;
if( i > 0 || !beof() )
j = set_linedata( head.ptr, bytes ) ;
else
j = ERROR ;
head.ptr = p ;
return j ;
}
static int get_max_memory( int size )
{
const int step = 128 * 1024 ; /* 128KBytes step */
char *buf = NULL ;
while( size > 0 )
{
size -= step ;
if( ( buf = malloc( size ) ) != NULL )
break ;
}
if( buf != NULL )
{
free( buf ) ;
if( (size -= step) > 0 )
return size ;
}
return 0 ;
}
static void mem_err( char *msg, int a, int b )
{
char buf[80] ;
strcpy( buf, msg ) ;
strcat( buf, " [" ) ;
strcat( buf, formdigitL( a>>10, 1, OFF ) ) ;
strcat( buf, "KB / " ) ;
strcat( buf, formdigitL( b>>10, 1, OFF ) ) ;
strcat( buf, "KB]" ) ;
report_fatal_error( ERR_FILE, buf ) ;
}
HEADER *read_sub( char *file, readtype_t reform )
{
FILE *fp = NULL ;
char *p ;
int org_fsize ;
if( head.filehead.file != NULL ) /* 開放されてない */
free_head() ;
head.now_block = -1, head.now_line = 0, head.now_linelow = LINEPTRs ;
file_ptr = NULL ;
if( reform == FILE_REFORM && head.filebuf != NULL ) /* タブサイズ変更 */
;
else
{
head.readsize = 0 ;
if( ( fp = fopen( file, "rb" ) ) == NULL )
{
report_fatal_error( ERR_FILE, "オープンに失敗" ) ;
return NULL ;
}
file_ptr = fp ;
head.fsize = org_fsize = get_fsize( fp ) ;
if( head.fsize > 1024 && reform == FILE_PREVIEW )
head.fsize = 1024 ;
if( head.filebuf != NULL )
free( head.filebuf ) ;
if( ( head.filebuf = malloc( (size_t)head.fsize+1 ) ) == NULL )
{
if( ( head.fsize = get_max_memory( head.fsize ) ) < 1 ||
( head.filebuf = malloc( (size_t)head.fsize+1 ) ) == NULL )
{
fclose( fp ) ;
report_fatal_error( ERR_FILE, "メモリ不足" ) ;
return NULL ;
}
mem_err( "ファイル全体が読めない", head.fsize, org_fsize ) ;
}
fseek( fp, 0L, SEEK_SET ) ;
}
head.readpos = 0 ;
head.ptr = head.filebuf ; /* ファイルデータの開始位置 */
/* ファイルヘッダのデータを初期化 */
head.filehead.file = strdup( file ) ;
if( ( p = jstrrchr( head.filehead.file, '\\' ) ) == NULL &&
( p = strchr( head.filehead.file, ':' ) ) == NULL )
head.filehead.name = head.filehead.file ;
else
head.filehead.name = p + 1 ;
head.filehead.cur_pos = head.filehead.line_now =
head.filehead.line_max = head.filehead.line_num = 0 ;
/* ファイルのデータを参照して行管理テーブルにセット */
if( set_linedata( "", 0 ) != ERROR ) /* 最初の番兵 */
while( read_line() != ERROR ) ;
while( read_file() > 0 ) ; /* ファイルの読み込みは最後までやる */
/* ファイルの末端に届いているかどうか */
if( ( !beof() || head.now_line < 1 ) && reform != FILE_PREVIEW )
mem_err( "ファイル全体を整形できない", head.readpos, head.fsize ) ;
set_linedata( "", 0 ) ; /* 最後の番兵 */
head.filehead.line_max = head.now_line - 1 ;
if( fp != NULL )
fclose( fp ) ;
return &head.filehead ;
}